package cn.coufran.springboot.starter.auth.impl.session;

import cn.coufran.springboot.starter.auth.AuthUser;
import cn.coufran.springboot.starter.auth.AuthUserManager;
import cn.coufran.springboot.starter.auth.Certificate;
import jakarta.servlet.http.HttpSession;

/**
 * 基于Session的权限上下文
 * @author Coufran
 * @version 1.0.0
 * @since 1.0.0
 */
public class SessionAuthUserManager implements AuthUserManager {
    /** Session中的数据key值 */
    private static final String ATTRIBUTE_NAME_AUTH = "auth";

    /** Session */
    private HttpSession session;

    /**
     * 构造权限上下文
     * @param session Session对象（Spring代理对象）
     */
    public SessionAuthUserManager(HttpSession session) {
        this.session = session;
    }

    /**
     * 重新加载实名用户，从Session中取出数据，重新构造权限用户
     * @param certificate 证书
     * @param <D> 数据类型
     * @return 权限用户，未认证返回null
     */
    @Override
    public <D> AuthUser<D> reloadAuthenticated(Certificate certificate) {
        D data = (D) session.getAttribute(ATTRIBUTE_NAME_AUTH);
        if (data == null) {
            return null;
        }
        return new SessionAuthUser(this, data);
    }

    /**
     * 构造匿名权限用户
     * @param <D> 数据类型
     * @return 权限用户
     */
    @Override
    public <D> AuthUser<D> createAnonymous() {
        return new SessionAuthUser<>(this);
    }

    /**
     * 接受登录，将数据存入Session中
     * @param authUser 权限用户
     * @param data 基础数据
     * @param <U> 数据类型
     * @return 访问证书
     */
    public <U> Certificate acceptLogin(AuthUser<U> authUser, U data) {
        session.setAttribute(ATTRIBUTE_NAME_AUTH, data);
        return new SessionCertificate();
    }

    /**
     * 刷新AccessToken
     * @param authUser 权限用户
     * @param <D> 权限用户基础数据类型
     * @return 新的权限证书
     */
    @Override
    public <D> Certificate acceptRefresh(AuthUser<D> authUser) {
        return new SessionCertificate();
    }

    /**
     * 权限用户登出上下文，移除Session中的数据
     * @param authUser 权限用户
     * @param <U> 权限用户基础数据类型
     */
    public <U> void acceptLogout(AuthUser<U> authUser) {
        session.removeAttribute(ATTRIBUTE_NAME_AUTH);
    }
}
